package pl.edu.agh.experts.diseases;

import java.util.LinkedList;
import java.util.List;

import org.drools.KnowledgeBase;
import org.drools.runtime.StatefulKnowledgeSession;

import pl.edu.agh.experts.diseases.commons.Decision;
import pl.edu.agh.experts.diseases.commons.Diseases;
import pl.edu.agh.experts.diseases.commons.IDisease;
import pl.edu.agh.experts.diseases.commons.MetaKnowledge;
import pl.edu.agh.experts.diseases.commons.Symptom;
import pl.edu.agh.experts.diseases.gui.MainWindow;

public class QuestionProvider {

	private KnowledgeBase kbase;
	private KnowledgeBase kbaseResults;
	private DiseaseHolder diseaseHolder;
	private boolean continueAsking;
	private List<MetaKnowledge> metaToAsk;
	private List<Symptom> symptomsToAsk;
	private static double questionStopValue = 0.85;
	private static QuestionStrategyProvider strategy;
	private InterfaceType interfaceType;

	public QuestionProvider(KnowledgeBase kbase, KnowledgeBase kbaseResults, DiseaseHolder diseaseHolder,
			QuestionStrategyProvider strategy, InterfaceType interfaceType) {
		this.kbase = kbase;
		this.kbaseResults = kbaseResults;
		this.diseaseHolder = diseaseHolder;
		continueAsking = true;
		metaToAsk = new LinkedList<MetaKnowledge>();
		for (MetaKnowledge meta : MetaKnowledge.values()) {
			metaToAsk.add(meta);
		}
		symptomsToAsk = new LinkedList<Symptom>();
		for (Symptom symptom : Symptom.values()) {
			symptomsToAsk.add(symptom);
		}
		QuestionProvider.strategy = strategy;
		this.interfaceType = interfaceType;
	}

	public boolean askPatient() {
		if (!continueAsking) {
			return false;
		}
		if (metaToAsk.size() > 0) {
			askMetaKnoweledge(metaToAsk.get(0));
		} else if (symptomsToAsk.size() > 0) {
			Symptom symptom = symptomsToAsk.get(0);
			if (interfaceType == InterfaceType.Console) {
				ConsoleUI.setQuestion(symptom, kbaseResults, this);
			} else if (interfaceType == InterfaceType.GUI) {
				MainWindow.getInstance().setQuestion(symptom, kbaseResults, this);
			}
		} else {
			return false;
		}
		return true;
	}

	public boolean respondToQuestion(Question q, Symptom symptom) {
		StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
		ksession.insert(q);
		ksession.insert(diseaseHolder);
		ksession.fireAllRules();
		symptomsToAsk.remove(symptom);
		for (Diseases disease : Diseases.values()) {
			ksession = kbase.newStatefulKnowledgeSession();
			ksession.insert(diseaseHolder);
			ksession.insert(disease);
			ksession.insert(this);
			ksession.insert(strategy);
			ksession.fireAllRules();
		}
		if (!continueAsking) {
			return false;
		}
		return true;
	}

	public void updateQuestionOrder() {
		List<IDisease> diseaseList = new LinkedList<IDisease>();
		for (IDisease disease : diseaseHolder.getAllDiseases()) {
			int i = 0;
			while (i < diseaseList.size()) {
				if (disease.getWeight() > diseaseList.get(i).getWeight()) {
					break;
				}
				i++;
			}
			diseaseList.add(i, disease);
		}
		for (IDisease disease : diseaseList) {
			for (Symptom symptom : symptomsToAsk) {
				if (disease.getSymptomsLeft().contains(symptom)) {
					symptomsToAsk.remove(symptom);
					symptomsToAsk.add(0, symptom);
					return;
				}
			}
		}
	}

	public void updateQuestionOrderRandom() {
		if (symptomsToAsk.size() > 1) {
			Symptom symptom = symptomsToAsk.get((int) (Math.random() * symptomsToAsk.size()));
			symptomsToAsk.remove(symptom);
			symptomsToAsk.add(0, symptom);
		}
	}

	public void stopAsking() {
		continueAsking = false;
	}

	private void askMetaKnoweledge(MetaKnowledge metaKnowledge) {
		metaToAsk.remove(metaKnowledge);
		if (interfaceType == InterfaceType.Console) {
			ConsoleUI.setMetaQuestion(metaKnowledge, kbaseResults, this);
		} else if (interfaceType == InterfaceType.GUI) {
			MainWindow.getInstance().setMetaQuestion(metaKnowledge, kbaseResults, this);
		}
	}

	public void respondToMetaQuestion(MetaKnowledge metaKnowledge, UserResponse response) {
		if (response.getDecision() == Decision.No) {
			for (Symptom symptom : metaKnowledge.getKnoweledge().keySet()) {
				StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
				Question q = new Question(symptom, metaKnowledge.getKnoweledge().get(symptom));
				ksession.insert(q);
				ksession.insert(diseaseHolder);
				ksession.fireAllRules();
				symptomsToAsk.remove(symptom);
			}
		}
	}

	public static double getQuestionStopValue() {
		return questionStopValue;
	}

	public static void setQuestionStopValue(double questionStopValue) {
		QuestionProvider.questionStopValue = questionStopValue;
	}

	public static QuestionStrategyProvider getStrategy() {
		return strategy;
	}

	public static void setStrategy(QuestionStrategyProvider strategy) {
		QuestionProvider.strategy = strategy;
	}
}
